﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SystemAnalizer.Models;
using SystemAnalizer.Common;

namespace SystemAnalizer.Algorithms
{
    public class Samuelson
    {
        private  int row;
        private int column;

        private int discretesQuantity;
        private MatrixOfDiscretes matrixDiscretes;
        private MatrixOfDiscretes discretesOfSamuelsonMatrix;
        public Samuelson(double[, ,]  matrix, int row, int column, string param, int tnyu, double H, int discretesQuantity)
        {
            this.discretesQuantity = discretesQuantity;

            this.row = row;
            this.column = column;

            matrixDiscretes = new MatrixOfDiscretes(row, column, param, tnyu, H, discretesQuantity);
            /*
            for(int i = 0; i < row; ++i)
                for(int j = 0; j < column; ++j)
                {
                    //matrixDiscretes.setDiscrete(i, j, matrix->formula(i,j) );  //nayel
                }
             */
            for (int l = 0; l < this.discretesQuantity; l++)
                for (int i = 0; i < this.row; i++)
                    for (int j = 0; j < this.column; j++)
                    {
                        this.matrixDiscretes.setDiscrete(l, i, j, matrix[l, i, j]);
                    }

            int rowCountOfR = 1;
            int columnCountOfR = column - 1;

            int rowCountOfS = row-1;
            int columnCountOfS = 1;

            int rowCountOfM = row-1;
            int columnCountOfM = column -1;

            int rowCountOfSamuelson = row;
            int columnCountOfSamuelson = 2 * column;

            MatrixOfDiscretes R = new MatrixOfDiscretes(rowCountOfR, columnCountOfR, param, tnyu, H, discretesQuantity);
            MatrixOfDiscretes S = new MatrixOfDiscretes(rowCountOfS, columnCountOfS, param, tnyu, H, discretesQuantity);
            MatrixOfDiscretes M = new MatrixOfDiscretes(rowCountOfM, columnCountOfM, param, tnyu, H, discretesQuantity);

            discretesOfSamuelsonMatrix = new MatrixOfDiscretes(rowCountOfSamuelson, columnCountOfSamuelson, param, tnyu, H, discretesQuantity);

            for(int j = 0; j < columnCountOfR; ++j)
                for(int k = 0; k < discretesQuantity; ++k)
                {
                    R.setDiscrete(rowCountOfR-1, j, k, matrixDiscretes.getDiscrete(rowCountOfR-1, j+1, k));
                }
            for(int i = 0; i < rowCountOfS; ++i)
                for(int k = 0; k < discretesQuantity; ++k)
                {
                    S.setDiscrete(i, columnCountOfS-1, k, matrixDiscretes.getDiscrete(i+1, columnCountOfS-1, k));
                }
            for(int i = 0; i < M.getRowCount(); ++i)
                for(int j = 0; j < M.getColumnCount(); ++j)
                    for(int k = 0; k < discretesQuantity; ++k)
                    {
                        M.setDiscrete(i, j, k, matrixDiscretes.getDiscrete(i+1, j+1, k));
                    }

            //Set 0x0 element
            for(int k = 0; k < discretesQuantity; ++k)
            {
                discretesOfSamuelsonMatrix.setDiscrete(0, 0, k, matrixDiscretes.getDiscrete(0,0,k));
            }

            //inital values for Samuelson matrix
            //set 0x0 to (n-1)x(n-1) parts
            MatrixOfDiscretes tmpMatrixOfDiscrets = R;
            for(int i = 0; i < discretesOfSamuelsonMatrix.getRowCount(); ++i)
            {
                for(int j = 0; j < R.getColumnCount(); ++j)
                    for(int k = 0; k < discretesQuantity; ++k)
                    {
                        discretesOfSamuelsonMatrix.setDiscrete(i, j, k, tmpMatrixOfDiscrets.getDiscrete(0, j, k));
                    }
                tmpMatrixOfDiscrets = tmpMatrixOfDiscrets.Multiply(M);
            }
    //inital values for Samuelson matrix
            //set 0x(n) to nx(n-1) parts
            // MatrixOfDiscretes tmpMatrixOfDiscrets1 = *R;
        for(int i = 0; i < discretesOfSamuelsonMatrix.getRowCount(); ++i)
        {
            MatrixOfDiscretes tmpM = M;
            tmpM.E();
            for(int j = R.getColumnCount(); j < discretesOfSamuelsonMatrix.getColumnCount(); ++j)
              if(j < discretesOfSamuelsonMatrix.getColumnCount() - i - 2)
              {
                    for(int k = 0; k < discretesQuantity; ++k)
                    {
                      discretesOfSamuelsonMatrix.setDiscrete(i, j, k, 0);
                    }
              }
              else if(j == discretesOfSamuelsonMatrix.getColumnCount() - i - 2 )
              {
                   //set 1
                  discretesOfSamuelsonMatrix.setDiscrete(i, j, 0, 1);
                  for(int k = 1; k < discretesQuantity; ++k)
                    {
                        discretesOfSamuelsonMatrix.setDiscrete(i,j,k, 0);
                    }
              }
              else if(j == discretesOfSamuelsonMatrix.getColumnCount() - i - 1 )
              {
                  //set -a11
                  for(int k = 0; k < discretesQuantity; ++k)
                    {
                        discretesOfSamuelsonMatrix.setDiscrete(i, j, k, -matrixDiscretes.getDiscrete(0, 0, k));
                    }
              } else if(j >= discretesOfSamuelsonMatrix.getColumnCount() - i )
              {
                    //set RM^nS
                    MatrixOfDiscretes tmp = R.Multiply(tmpM.Multiply(S));
                    tmpM = tmpM.Multiply(M);
                    for(int k = 0; k < discretesQuantity; ++k)
                      {
                          discretesOfSamuelsonMatrix.setDiscrete(i, j, k, -tmp.getDiscrete(0, 0, k));
                      }
              }
    }
}

public void calculate()
{
    for(int i = 0; i < discretesOfSamuelsonMatrix.getRowCount()-1; ++i) // all A[i][l] l=i,row elements will be equalized to 0
    {
        //discretesOfSamuelsonMatrix.show();
        if(discretesOfSamuelsonMatrix.getDiscrete(i, i, 0) == 0)
        {
            for(int l = i+1; l < discretesOfSamuelsonMatrix.getRowCount(); ++l)
            {
                if(discretesOfSamuelsonMatrix.getDiscrete(l, i, 0) != 0)
                {
                    discretesOfSamuelsonMatrix.SwapRows(i, l);
                    break;
                }
            }
        }
        //discretesOfSamuelsonMatrix->show();
        if(discretesOfSamuelsonMatrix.getDiscrete(i, i, 0) != 0)
        {
            List<double> d   = new List<double>();
            List<double> d1  = new List<double>();;
            List<double> dli = new List<double>();;
            for(int l = i+1; l < discretesOfSamuelsonMatrix.getRowCount(); ++l )
            {
                dli = discretesOfSamuelsonMatrix.getDiscretes(l, i);
                for(int j = i; j < discretesOfSamuelsonMatrix.getColumnCount(); ++j)
                {
                    d1 = discretesOfSamuelsonMatrix.Divide(i, j, i, i );
                    d = discretesOfSamuelsonMatrix.Multiply(d1, dli);
                    for(int k = 0; k < discretesQuantity; ++k)
                    {
                        d[k] = d[k] - discretesOfSamuelsonMatrix.getDiscrete(l, j, k);
                    }
                    discretesOfSamuelsonMatrix.setDiscrete(l, j, d);
                }
            }

        }
        else
        {
           // qDebug() << "chem karox bajanel 0-i";
        }
    }
        //discretesOfSamuelsonMatrix->show();

}


MatrixOfDiscretes getDiscretesOfSamuelsonMatrix()
{
    return discretesOfSamuelsonMatrix;
}
    }
}
